Ender.Game.Repositories.RepositoryFactory = {

	createEnemyRepository : function(data) {
		// TODO mock enemy repository
		var enemyData = {
			id : "sickle-peasant",
			className : "Peasant",
			animation : "heroes2-peasant",

			attributes : {
				strength : 10,
				dexterity : 8,
				constitution : 10,
				wisdom : 10,
				intelligence : 10,
				charisma : 8
			},
			
			inventory : {
				mainHand : "bronze-sickle"
			},
			
			feats : []
		};

		var enemy = new Ender.Game.Classes.Enemy();

		enemy.id = enemyData.id;
		enemy.className = enemyData.className;
		enemy.animation = Ender.Game.Repositories.AnimationRepository[enemyData.animation];

		for ( var attribute in enemyData.attributes) {
			enemy.attributes[attribute] = enemyData.attributes[attribute];
		}
		enemy.computeStats();

		for ( var inventorySlot in enemyData.inventory) {
			var itemId = enemyData.inventory[inventorySlot];
			if (Ender.Game.Repositories.ItemRepository.Weapons[itemId])
				enemy.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Weapons[itemId];
			if (Ender.Game.Repositories.ItemRepository.Shields[itemId])
				enemy.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Shields[itemId];
			if (Ender.Game.Repositories.ItemRepository.Armors[itemId])
				enemy.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Armors[itemId];
			if (Ender.Game.Repositories.ItemRepository.Accessories[itemId])
				enemy.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Accessories[itemId];
		}

		for ( var i = 0; i < enemyData.feats.length; i++) {
			var featId = enemyData.feats[i];
			var feat = Ender.Game.Repositories.FeatRepository[featId];

			if (!enemy.feats[feat.type]) {
				enemy.feats[feat.type] = [];
			}

			enemy.feats[feat.type].push(feat);
			feat.apply(enemy);
		}

		Ender.Game.Repositories.EnemyRepository = {

			getRandomEnemyForCharacter : function(character) {
				return enemy;
			}
		};
	},

	createObstacleRepository : function(data) {

	},

	applyFeatTemplates : function(data) {
		if (!Ender.Game.Repositories.FeatRepository)
			Ender.Game.Repositories.FeatRepository = {};

		var repo = Ender.Game.Repositories.FeatRepository;
		for ( var i = 0; i < data.length; i++) {
			var featTemplate = data[i];

			if (featTemplate.parameter == "weaponType") {
				// apply for all weapon types
				for ( var weaponTypeId in Ender.Game.Repositories.ItemTypeRepository.WeaponTypes) {
					var weaponType = Ender.Game.Repositories.ItemTypeRepository.WeaponTypes[weaponTypeId];
					var featTemplateClone = angular.copy(featTemplate);

					var featId = featTemplateClone.id.replace(/{weaponType}/g, weaponType.id);
					var featData = {
						type : featTemplateClone.type,
						effect : featTemplateClone.effect,
						display : featTemplateClone.display
					};
					// change name and description to fit each weapon
					featData.display.name = featData.display.name.replace(/{weaponType}/g, weaponType.name);
					featData.display.description = featData.display.description.replace(/{weaponType}/g, weaponType.name);
					// apply weapon type to effect
					for ( var bonus in featData.effect) {
						featData.effect[bonus].weaponTypes = [ weaponType.id ];
					}

					var feat = new Ender.Game.Classes.Feat(featId, featData);
					repo[featId] = feat;
				}
			}
			
			if (featTemplate.parameter == "weaponArchetype") {
				for ( var j=0; j<Ender.Game.Repositories.ItemTypeRepository.WeaponArchetypes.length; j++) {
					var weaponArchetype = Ender.Game.Repositories.ItemTypeRepository.WeaponArchetypes[j];
					var featTemplateClone = angular.copy(featTemplate);
					
					var featId = featTemplateClone.id.replace(/{weaponArchetype.id}/g, weaponArchetype.id);
					var featData = {
						type : featTemplateClone.type,
						effect : featTemplateClone.effect,
						display : featTemplateClone.display
					};
					// change name and description to fit each weapon
					featData.display.name = featData.display.name.replace(/{weaponArchetype.typeName}/g, weaponArchetype.typeName);
					featData.display.description = featData.display.description.replace(/{weaponArchetype.typeName}/g, weaponArchetype.typeName);
					
					// apply weapon type to effect
					for ( var bonus in featTemplateClone.effect) {
						featData.effect[bonus].weaponTypes = [ weaponArchetype.id ];
					}
					
					var feat = new Ender.Game.Classes.Feat(featId, featData);
					repo[featId] = feat;
				}
			}
		}
	},

	createFeatRepository : function(data) {
		if (!Ender.Game.Repositories.FeatRepository)
			Ender.Game.Repositories.FeatRepository = {};

		var repo = Ender.Game.Repositories.FeatRepository;
		for ( var featId in data) {
			var featData = data[featId];
			var feat = new Ender.Game.Classes.Feat(featId, featData);
			repo[featId] = feat;
		}
	},

	createItemTypeRepository : function(data) {
		Ender.Game.Repositories.ItemTypeRepository = {};
		
		Ender.Game.Repositories.ItemTypeRepository.WeaponArchetypes = data["weapon-archetypes"];

		var weaponTypes = Ender.Game.Repositories.ItemTypeRepository.WeaponTypes = {};
		for ( var weaponTypeId in data.weapons) {
			var weaponTypeData = data.weapons[weaponTypeId];
			var weaponType = new Ender.Game.Classes.WeaponType(weaponTypeId, weaponTypeData);
			weaponTypes[weaponTypeId] = weaponType;
		}

		var shieldTypes = Ender.Game.Repositories.ItemTypeRepository.ShieldTypes = {};
		for ( var shieldTypeId in data.shields) {
			var shieldTypeData = data.shields[shieldTypeId];
			var shieldType = new Ender.Game.Classes.ShieldType(shieldTypeData);
			shieldTypes[shieldTypeId] = shieldType;
		}

		var armorTypes = Ender.Game.Repositories.ItemTypeRepository.ArmorTypes = {};
		for ( var armorTypeId in data.armor) {
			var armorTypeData = data.armor[armorTypeId];
			var armorType = new Ender.Game.Classes.ArmorType(armorTypeData);
			armorTypes[armorTypeId] = armorType;
		}

		var accessoryTypes = Ender.Game.Repositories.ItemTypeRepository.AccessoryTypes = {};
		for ( var accessoryTypeId in data.accessories) {
			var accessoryTypeData = data.accessories[accessoryTypeId];
			var accessoryType = new Ender.Game.Classes.AccessoryType(accessoryTypeData);
			accessoryTypes[accessoryTypeId] = accessoryType;
		}
	},

	createItemRepository : function(data) {
		Ender.Game.Repositories.ItemRepository = {};

		var weapons = Ender.Game.Repositories.ItemRepository.Weapons = {};
		for ( var weaponId in data.weapons) {
			var weaponData = data.weapons[weaponId];
			var weaponType = Ender.Game.Repositories.ItemTypeRepository.WeaponTypes[weaponData.type];
			var weapon = new Ender.Game.Classes.Weapon();
			weapon.name = weaponData.name;
			weapon.material = weaponData.material;
			weapon.damage = weaponType.damage;
			weapon.critRange = weaponType.critRange;
			weapon.icon = weaponData.icon;

			weapons[weaponId] = weapon;
		}
		var shields = Ender.Game.Repositories.ItemRepository.Shields = {};
		for ( var shieldId in data.shields) {
			var shieldData = data.shields[shieldId];
			var shieldType = Ender.Game.Repositories.ItemTypeRepository.ShieldTypes[shieldData.type];
			// TODO add properties from shieldType
			var shield = new Ender.Game.Classes.Shield();
			shield.name = shieldData.name;
			shield.icon = shieldData.icon;

			shields[shieldId] = shield;
		}
		var armors = Ender.Game.Repositories.ItemRepository.Armors = {};
		for ( var armorId in data.armor) {
			var armorData = data.armor[armorId];
			var armorType = Ender.Game.Repositories.ItemTypeRepository.ArmorTypes[armorData.type];
			// TODO add properties from armorType
			var armor = new Ender.Game.Classes.Armor();
			armor.name = armorData.name;
			armor.material = armorData.material;

			if (armorType.partial)
				armor.partial = true;

			armor.icon = armorData.icon;

			armors[armorId] = armor;
		}
		var accessories = Ender.Game.Repositories.ItemRepository.Accessories = {};
		for ( var accessoryId in data.accessories) {
			var accessoryData = data.accessories[accessoryId];
			var accessoryType = Ender.Game.Repositories.ItemTypeRepository.AccessoryTypes[accessoryData.type];
			// TODO add properties from accessoryType
			var accessory = new Ender.Game.Classes.Accessory();
			accessory.name = accessoryData.name;
			accessory.icon = accessoryData.icon;

			accessories[accessoryId] = accessory;
		}
	},

	createCharacterRepository : function(data) {
		var repo = Ender.Game.Repositories.CharacterRepository = {};

		for ( var characterId in data) {
			var characterData = data[characterId];
			var character = new Ender.Game.Classes.Character();
			character.id = characterId;
			character.className = characterData.className;
			character.universe = characterData.universe;
			character.animation = Ender.Game.Repositories.AnimationRepository[characterData.animation];
			for ( var attribute in characterData.attributes) {
				character.attributes[attribute] = characterData.attributes[attribute];
			}
			character.computeStats();

			for ( var inventorySlot in characterData.inventory) {
				var itemId = characterData.inventory[inventorySlot];
				if (Ender.Game.Repositories.ItemRepository.Weapons[itemId])
					character.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Weapons[itemId];
				if (Ender.Game.Repositories.ItemRepository.Shields[itemId])
					character.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Shields[itemId];
				if (Ender.Game.Repositories.ItemRepository.Armors[itemId])
					character.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Armors[itemId];
				if (Ender.Game.Repositories.ItemRepository.Accessories[itemId])
					character.inventory[inventorySlot] = Ender.Game.Repositories.ItemRepository.Accessories[itemId];
			}

			for ( var i = 0; i < characterData.feats.length; i++) {
				var featId = characterData.feats[i];
				var feat = Ender.Game.Repositories.FeatRepository[featId];

				if (!character.feats[feat.type]) {
					character.feats[feat.type] = [];
				}

				character.feats[feat.type].push(feat);
				feat.apply(character);
			}

			repo[characterId] = character;
		}
	},

	createChoiceRepository : function(data) {

		var addCategoryChoicesToRepo = function(choice) {
			Ender.Game.Repositories.ChoiceRepository[choice.id] = choice;
			for ( var i = 0, length = choice.categories.length; i < length; i++) {
				addCategoryChoicesToRepo(choice.categories[i]);
			}
		};

		Ender.Game.Repositories.ChoiceRepository = {};
		var rootChoice = new Ender.Game.Classes.StartingChoice(data, null);
		addCategoryChoicesToRepo(rootChoice);
	},

	createAnimationRepository : function(data) {
		Ender.Game.Repositories.AnimationRepository = {};

		for ( var animationId in data) {
			var animationData = data[animationId];
			Ender.Game.Repositories.AnimationRepository[animationId] = new Ender.Game.Classes.Animation(animationId, animationData);
		}
	},

	createArenaRepository : function(data) {
		var repo = Ender.Game.Repositories.ArenaRepository = {};

		for ( var arenaId in data) {
			var arenaData = data[arenaId];
			repo[arenaId] = new Ender.Game.Classes.ArenaPrototype(arenaId, arenaData);
		}

		Ender.Game.Repositories.ArenaRepository.getArenaForCharacter = function(character) {
			if (character.getEquippedWeapon().isOfType('ranged'))
				return 'grove';
			else
				return "concrete-yard";
		};
	}
};
